//
// Created by 陈奕锟 on 2022/11/20.
//

#ifndef AUTOMATICTELLER_DISPATCHER_HPP
#define AUTOMATICTELLER_DISPATCHER_HPP

#endif //AUTOMATICTELLER_DISPATCHER_HPP
#pragma once

#include "message.hpp"
#include "TemplateDispatcher.hpp"

namespace messaging
{
    class close_queue   // * 示意关闭队列的消息
    {};

    class dispatcher
    {
    private:
        queue* q;
        bool chained;

        dispatcher(dispatcher const&) = delete; // * dispatcher实例不可复制
        dispatcher& operator= (dispatcher const&) = delete;

        template<
                typename Dispatcher,
                typename Msg,
                typename Func
                >
        friend class TemplateDispatcher;

        void wait_and_dispatch()
        {
            for (;;)    // * 无限循环，等待消息并发送
            {
                auto msg = q -> wait_and_pop();
                dispatch(msg);
            }
        }

        bool dispatch(std::shared_ptr<message_base> const& msg)
        {
            if ( dynamic_cast<wrapped_message<close_queue>* >( msg.get() ) )
            {
                throw close_queue();
            }

            return false;
        }

    public:
        dispatcher(dispatcher&& other)  // * dispatcher是可移动的实例
            : q(other.q), chained(other.chained)
        {
            other.chained = true;   // * 上游消息分发者不会等待消息
        }

        explicit dispatcher(queue* i_q)
            : q(i_q), chained(false)
        {}

        template<typename Message, typename Func>
        TemplateDispatcher<dispatcher, Message, Func>
        handle(Func&& func)
        {
            return TemplateDispatcher<dispatcher, Message, Func>(
                    q, this, std::forward<Func>(func) );
        }

        ~dispatcher() noexcept(false)   // * 保留析构函数抛出异常的可能
        {
            if (!chained)
            {
                wait_and_dispatch();
            }
        }
    };
}